#include "includes.h"		//biblioteka zawierające pliki nagłowkowe dołączane do projektu
int main(void) {
	uint16_t T, T2;
	loadMEMC("file_code.bin");
	loadMEMD("file_data.bin");
	setPC(0x0000);
	InitializeFlagRegister();

#if _DEBUG_MODE
	int i = 0;
	printf("MEMC\n");
	for (i = 0; i < 10; i++)
		printf("0x%lx\n", getMEMC(i));

	printf("MEMD\n");
	for (i = 0; i < 10; i++)
		printf("0x%lx\n", getMEMD(i));
#endif
	GLOBAL_ERROR = 0;
	for (;;) {
		T = getMEMC(getPC());
		printf("TEST MAIN SWITCH%x, %x\n", T & 0xFF00, (T & 0xFF00) >> 12);
		printf("0x%04x: 0x%04x\n", getPC(), T);
		printf("GLOBAL ERROR = %d\n", GLOBAL_ERROR);
		switch ((T & 0xF000) >> 12) {

		if (GLOBAL_ERROR != 0) {
			return -1;
		} else {
			case OPCODE_AND_OR:
			{
				printf("TEST  AND OR %lx, %lx\n", (T & 0x0F00) >> 8, (((T
						& 0x0F00) >> 8) & 0b1100) >> 10);
				switch ((((T & 0x0F00) >> 8) & 0b1100) >> 2) {
				case OPCODE_AND:
					F_AND();
					printMEMD();
					break;

				case OPCODE_OR:
					F_OR();
					printMEMD();
					break;

				default:
					GLOBAL_ERROR = -1;
					printf(
							"ERROR. WRONG INSTRUCTION. CODE %d\n (PC=0x%lx, T=0x%lx)\r\n",
							GLOBAL_ERROR, getPC(), T);
					saveMEMD("file_data.bin");
					return -1;
				}
				break;
			}
			case OPCODE_BR:
			{
				printf("TEST T = %x, BRANCH = %x\n", T, ((T & 0x000F) & 0b0111));
				switch ((T & 0x000F) & 0b0111) {

				case OPCODE_BRVS:
					F_BRVS();
					printMEMD();
					break;

				case OPCODE_BRHS:
					F_BRHS();
					printMEMD();
					break;

				case OPCODE_BRPL:
					F_BRPL();
					printMEMD();
					break;

				case OPCODE_BRCC:
					F_BRCC();
					printMEMD();
					break;

				default: {
					GLOBAL_ERROR = -1;
					printf(
							"ERROR. WRONG INSTRUCTION. CODE %d\n (PC=0x%lx, T=0x%lx)\r\n",
							GLOBAL_ERROR, getPC(), T);
					saveMEMD("file_data.bin");
					return -1;
				}
				}
				break;
			}

			case OPCODE_CL_INC_SEH_SWAP_SBIC_LD2_3_6_7_8:
			{
				printf("TEST CL_INC_LD2_LD3 T = %lx, CL = %x\n", T,
						(T & 0x000F));
				SHOW_PC
				switch ((T & 0x000F)) {

				case OPCODE_CL: {
					switch ((T & 0x00F0) >> 4) {

					case OPCODE_CLT:
						F_CLT();
						printMEMD();
						break;

					case OPCODE_CLH:
						F_CLH();
						printMEMD();
						break;

					case OPCODE_SEH:
						F_SEH();
						printMEMD();
						break;

					case OPCODE_SET:
						F_SET();
						printMEMD();
						break;

					default: {
						GLOBAL_ERROR = -1;
						printf(
								"ERROR. WRONG INSTRUCTION. CODE %d\n (PC=0x%lx, T=0x%lx)\r\n",
								GLOBAL_ERROR, getPC(), T);
						saveMEMD("file_data.bin");
						return -1;
					}

					}
					break;
				}
				case OPCODE_INC:
					F_INC();
					printMEMD();
					break;

				case OPCODE_LD2:
					F_LD2();
					printMEMD();
					break;

				case OPCODE_LD3:
					F_LD3();
					printMEMD();
					break;

				case OPCODE_LD6:
					F_LD6();
					printMEMD();
					break;

				case OPCODE_LD7_SWAP: {
					printf(" LD7 SWAP\n");
					SHOW_PC
					switch ((((T & 0x0F00) >> 8) & 0b1110) >> 1) {
					case OPCODE_LD7:
						F_LD7();
						printMEMD();
						break;

					case OPCODE_SWAP:
						F_SWAP();
						printMEMD();
						break;
					default:
					{
						GLOBAL_ERROR = -1;
						printf(
								"ERROR. WRONG INSTRUCTION. CODE %d\n (PC=0x%lx, T=0x%lx)\r\n",
								GLOBAL_ERROR, getPC(), T);
						saveMEMD("file_data.bin");
						return -1;
					}

				}
					break;
				}
				//-------------------------------UWAGA!!!----------------------------------------
				default:
				{
					//DOPISAĆ ELSE
					F_LDDZ();
					printMEMD();
					break;
				}
			}
			break;
		}

	case OPCODE_CPSE_ROL: {
		printf("TEST CPSE_ROL T = %lx, LAST 4 bits = 0x%04x\n", T,
				((T & 0x0F00) >> 10));
		switch (((T & 0x0F00) >> 10)) {
		case OPCODE_CPSE:
			F_CPSE();
			printMEMD();
			break;
		case OPCODE_ROL:
			F_ROL();
			printMEMD();
			break;
		default: {
			GLOBAL_ERROR = -1;
			printf(
					"ERROR. WRONG INSTRUCTION. CODE %d\n (PC=0x%lx, T=0x%lx)\r\n",
					GLOBAL_ERROR, getPC(), T);
			saveMEMD("file_data.bin");
			return -1;
		}
		}
		break;
	}
	case OPCODE_LD1_4v1_5: {
		printf("TEST LD1_LD4v1 T = %lx, LAST 4 bits = %x\n", T, (T & 0x000F));
		switch (T & 0x000F) {
		case OPCODE_LD1:
			F_LD1();
			printMEMD();
			break;
		case OPCODE_LD5:
			F_LD5();
			printMEMD();
			break;
			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!UWAGA!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		default: {
			if (((T & 0x000F) & 0b1000) >> 3 == 1) {
				F_LD4();
				printMEMD();
				break;
			} else if (((T & 0x000F) & 0b1000) >> 3 == 0) {
				F_LDDZ();
				printMEMD();
				break;
			} else {
				GLOBAL_ERROR = -1;
				printf(
						"ERROR. WRONG INSTRUCTION. CODE %d\n (PC=0x%lx, T=0x%lx)\r\n",
						GLOBAL_ERROR, getPC(), T);
				saveMEMD("file_data.bin");
				return -1;
			}
		}
			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		}
		break;
	}
	case OPCODE_LD4v2_LDDZ: {
		printf("LDDY LDDZ 0x%04x\n", ((T & 0x000F) & 0b1000) >> 3);
		switch (((T & 0x000F) & 0b1000) >> 3) {
		case OPCODE_LD4v2:
			F_LD4();
			printMEMD();
			break;
		case OPCODE_LDDZ:
			F_LDDZ();
			printMEMD();
			break;
		default:
			GLOBAL_ERROR = -1;
			printf(
					"ERROR. WRONG INSTRUCTION. CODE %d\n (PC=0x%lx, T=0x%lx)\r\n",
					GLOBAL_ERROR, getPC(), T);
			saveMEMD("file_data.bin");
			return -1;
		}
		break;
	}
		F_LD4();
		printMEMD();
		break;

	case OPCODE_LD8:
		F_LDDZ();
		printMEMD();
		break;

	case OPCODE_MOVW:
		if (T == 0)
			return 0;
		else {
			F_MOVW();
			printMEMD();
			break;
		}

	default: {
		GLOBAL_ERROR = -1;
		printf("ERROR. WRONG INSTRUCTION. CODE %d\n (PC=0x%lx, T=0x%lx)\r\n",
				GLOBAL_ERROR, getPC(), T);
		saveMEMD("file_data.bin");
		return -1;
	}
		//saveMEMD("file_data.bin");
		} //Koniec funkcji IF
	}
}

return 0;
}
